package com.otto.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.otto.reggie.common.CustomException;
import com.otto.reggie.common.R;
import com.otto.reggie.dto.DishDto;
import com.otto.reggie.dto.SetmealDto;
import com.otto.reggie.entity.*;
import com.otto.reggie.service.CategoryService;
import com.otto.reggie.service.DishService;
import com.otto.reggie.service.SetmealDishService;
import com.otto.reggie.service.SetmealService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 作者：otto
 * 时间：2022-08-12 13:46:40
 */
@RestController
@Slf4j
@RequestMapping("/setmeal")
public class SetmealController {

    @Autowired
    private SetmealService setmealService;

    @Autowired
    private SetmealDishService setmealDishService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private DishService dishService;

    /**
     * 保存套餐信息并同时保存套餐内菜品信息
     *
     * @param setmealDto
     * @return
     */
    @PostMapping
    @Transactional
    public R<String> addSetMeal(@RequestBody SetmealDto setmealDto) {

        log.info("添加套餐时收到前端参数:{},以及套餐价格{}分", setmealDto, setmealDto.getPrice());

        //保存套餐信息
        setmealService.save(setmealDto);
        //保存套餐内的菜品信息
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        for (SetmealDish setmealDish : setmealDishes) {
            setmealDish.setSetmealId(setmealDto.getId());
        }
        setmealDishService.saveBatch(setmealDishes);

        return R.success("添加成功");
    }

    /**
     * 套餐分页信息
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize, String name) {
        log.info("套餐展示收到前端参数，页码:{},每页展示条数:{},套餐名字:{}", page, pageSize, name);
        //构建套餐分页
        Page<Setmeal> setmealPage = new Page<>(page, pageSize);
        LambdaQueryWrapper<Setmeal> setmealQueryWrapper = new LambdaQueryWrapper<>();
        if (name != null) {
            //name.trim();
            setmealQueryWrapper.like(StringUtils.isNotBlank(name), Setmeal::getName, name);
        }
        setmealQueryWrapper.orderByDesc(Setmeal::getUpdateTime);
        //填充查询到的套餐信息，但此时只有套餐分类id，无套餐分类名
        setmealPage = setmealService.page(setmealPage, setmealQueryWrapper);

        //新建需要返回的含套餐信息的分页
        Page<SetmealDto> setmealDtoPage = new Page<>(page, pageSize);
        //复制分页信息，除了records
        BeanUtils.copyProperties(setmealPage, setmealDtoPage, "records");
        //遍历查到的套餐信息集合，并同时新建一个DTO对象并赋值（包括套餐分类名称）
        List<SetmealDto> collect = setmealPage.getRecords().stream().map((item) -> {
            SetmealDto setmealDto = new SetmealDto();
            BeanUtils.copyProperties(item, setmealDto);
            Long categoryId = item.getCategoryId();
            Category category = categoryService.getById(categoryId);
            if (category != null) {
                String categoryName = category.getName();
                setmealDto.setCategoryName(categoryName);
            }
            return setmealDto;
        }).collect(Collectors.toList());
        setmealDtoPage.setRecords(collect);

        return R.success(setmealDtoPage);
    }

    /**
     * 停售套餐
     *
     * @param ids
     * @return
     */
    @PostMapping("/status/0")
    public R<String> stopSetmealSell(Long[] ids) {
        if (ids.length == 0) {
            return R.error("没有选中");
        }
        for (Long id : ids) {
            log.info("收到需要停售的套餐id:" + id);
            Setmeal setmeal = setmealService.getById(id);
            setmeal.setStatus(0);
            setmealService.updateById(setmeal);
        }
        return R.success("已将全部所选套餐停售");
    }

    /**
     * 启售套餐
     *
     * @param ids
     * @return
     */
    @PostMapping("/status/1")
    public R<String> startSetmealSell(Long[] ids) {
        if (ids.length == 0) {
            return R.error("没有选中");
        }
        //用来保存可以启售的套餐
        List<Setmeal> sellAbleSetmeal = new ArrayList<>();
        //用来保存不可以启售的套餐
        List<Setmeal> sellUnAbleSetmeal = new ArrayList<>();
        //保存已经停售的菜品以及对应的套餐
        HashMap<Setmeal, List<Dish>> stopSellDishOfSetmeals = new HashMap<>();
        //遍历每一个套餐，查询改套餐中有无已经停售的菜品
        for (Long id : ids) {
            log.info("收到需要启售的套餐id:" + id);
            //获取套餐对象
            Setmeal setmeal = setmealService.getById(id);
            LambdaQueryWrapper<SetmealDish> setmealDishQueryWrapper = new LambdaQueryWrapper<>();
            setmealDishQueryWrapper.eq(SetmealDish::getSetmealId, id);
            //查到该套餐包含的所有菜品集合
            List<SetmealDish> SetmealDishs = setmealDishService.list(setmealDishQueryWrapper);
            //新建一个集合，保存该套餐内停售的菜品
            List<Dish> stopSellDishes = new ArrayList<>();
            //标志该套餐能否启售，true为可以
            boolean start = true;
            //遍历菜品集合，查看该菜品是否停售
            for (SetmealDish setmealDish : SetmealDishs) {
                Long dishId = setmealDish.getDishId();
                //根据套餐的菜品信息获取菜品对象
                Dish dish = dishService.getById(dishId);
                //包含停售菜品，修改标志为false
                Integer status = null;
                if (dish == null) {
                    throw new CustomException("套餐" + setmeal.getName()
                            + "中的菜品id为" + dishId + "的不存在");
                }
                if (dish != null) {
                    status = dish.getStatus();
                }
                if (status == 0) {
                    start = false;
                    stopSellDishes.add(dish);
                }
            }
            //根据标志将对应的套餐添加到能否启售的集合
            if (start == true) {
                sellAbleSetmeal.add(setmeal);
                setmeal.setStatus(1);
                //启售套餐
                setmealService.updateById(setmeal);
            } else {
                sellUnAbleSetmeal.add(setmeal);
                //将该不能启售套餐和对应的停售的菜品添加进Map
                stopSellDishOfSetmeals.put(setmeal, stopSellDishes);
            }
        }


        if (sellUnAbleSetmeal.size() == 0) {
            log.info("以下套餐启售成功———>{}", sellAbleSetmeal);
            return R.success("已将全部所选菜品启售");
        } else {
            if (sellAbleSetmeal.size() > 0) {
                log.info("以下套餐启售成功———>{}", sellAbleSetmeal);
            }
            log.info("以下套餐启售失败———>{}", sellUnAbleSetmeal);

            stopSellDishOfSetmeals.forEach((k, v) -> {

                log.info("不能启售套餐:{}", k.getName());
                log.info("因为 ");
                for (Dish dish : v) {
                    log.info(" {菜品 {}} ", dish.getName());
                }
                log.info("正在停售！");

            });
            if (stopSellDishOfSetmeals.isEmpty()) {
                return R.success("已将所选套餐启售");
            } else {
                throw new CustomException("部分套餐启售失败");
            }
        }
    }

    /**
     * 根据setmealId回显套餐信息
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<SetmealDto> getById(@PathVariable Long id) {
        log.info("修改id为{}的套餐信息", id);
        //通过Id查询套餐信息
        Setmeal setmeal = setmealService.getById(id);
        //通过Id查询套餐菜品
        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId, id);
        List<SetmealDish> setmealDishes = setmealDishService.list(queryWrapper);
        //新建Dto对象
        SetmealDto setmealDto = new SetmealDto();
        //将查到的套餐信息赋值给dto
        BeanUtils.copyProperties(setmeal, setmealDto);
        //将套餐菜品信息赋值
        setmealDto.setSetmealDishes(setmealDishes);
        return R.success(setmealDto);
    }

    /**
     * 修改套餐信息
     *
     * @param setmealDto
     * @return
     */
    @PutMapping
    public R<String> updateById(@RequestBody SetmealDto setmealDto) {
        log.info("保存套餐信息 : {},以及套餐的名称: {}", setmealDto.toString(), setmealDto.getName());

        //保存套餐信息
        setmealService.updateById(setmealDto);
        //删除套餐原有菜品信息
        LambdaQueryWrapper<SetmealDish> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SetmealDish::getSetmealId, setmealDto.getId());
        setmealDishService.remove(queryWrapper);
        //如果有菜品信息
        if (setmealDto.getSetmealDishes() != null) {
            //提取页面的菜品信息
            List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
            //为每条菜品信息设置对应的套餐id
            setmealDishes = setmealDishes.stream().map((item) -> {
                item.setSetmealId(setmealDto.getId());
                return item;
            }).collect(Collectors.toList());
            setmealDishService.saveBatch(setmealDishes);
        }
        return R.success("保存成功");
    }

    /**
     * 批量删除套餐
     *
     * @param ids
     * @return
     */
    @DeleteMapping
    public R<String> deleteSetmealByIds(Long[] ids) {
        //创建集合保存正在启售的套餐
        ArrayList<String> setmealsUnablToDelete = new ArrayList<>();
        for (Long id : ids) {

            log.info("收到需要删除的套餐id:" + id);
            //1.检查套餐是否在售
            //查到套餐
            Setmeal setmeal = setmealService.getById(id);
            //套餐未在售
            if (setmeal!=null&&setmeal.getStatus()==0) {
                //删除套餐菜品表
                LambdaQueryWrapper<SetmealDish> setmealDishQueryWrapper = new LambdaQueryWrapper<>();
                setmealDishQueryWrapper.eq(SetmealDish::getSetmealId,id);
                setmealDishService.remove(setmealDishQueryWrapper);
                //删除套餐
                setmealService.removeById(id);
            }else if(setmeal==null){

            }else  {
                setmealsUnablToDelete.add(setmeal.getName());
            }

        }
        if (setmealsUnablToDelete.isEmpty()) {
            return R.success("已删除全部所选套餐");
        }
         else {
            throw new CustomException("不能删除在售套餐，有以下套餐未删除"+setmealsUnablToDelete);
        }

    }
    @GetMapping("/list")
    public R<List<Setmeal>> list(Setmeal setmeal){
        log.info("SetmealController.list方法收到参数：{}",setmeal);
        LambdaQueryWrapper<Setmeal> setmealQueryWrapper = new LambdaQueryWrapper<>();
        setmealQueryWrapper.eq(Setmeal::getCategoryId,setmeal.getCategoryId())
                .eq(Setmeal::getStatus,setmeal.getStatus());
        List<Setmeal> setmeals = setmealService.list(setmealQueryWrapper);
        return R.success(setmeals);
    }

}
